package com.runa.monitor.platinterface.netservice.equipment;

import com.runa.monitor.comm.dto.*;
import com.runa.monitor.platinterface.backwork.function.TaskFunction;
import com.runa.monitor.platinterface.netservice.connect.commstatus.CommStatus;
import com.runa.rccprotocol.dto.equdata.EquData;
import com.runa.rccprotocol.dto.hiwits.HiwitsRequestData;
import com.runa.rccprotocol.dto.param.ExtendParam;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Slf4j
public class HiwitsDriver extends NetEqu<String> {

    /**
     * 吉申特楼阀通用 BYTK modbus点位
     */
    private static List<Point> bvPoints;

    private static Integer[] bvIds;

    static {
        bvIds = new Integer[]{40001, 40003, 40010, 40012, 40014, 40016, 40018, 40020, 40032, 40033, 40034};
        bvPoints = new ArrayList<>();
        //设定开度
        bvPoints.add(new Point(bvIds[0],"16位整型", "AB", 0));
        //反馈开度
        bvPoints.add(new Point(bvIds[1],"16位整型", "AB", 0));
        //供水温
        bvPoints.add(new Point(bvIds[2],"浮点", "CDAB", 0));
        //回水温
        bvPoints.add(new Point(bvIds[3],"浮点", "CDAB", 0));
        //环境温
        bvPoints.add(new Point(bvIds[4],"浮点", "CDAB", 0));
        //供压
        bvPoints.add(new Point(bvIds[5],"浮点", "CDAB", 0));
        //阀后压
        bvPoints.add(new Point(bvIds[6],"浮点", "CDAB", 0));
        //阀前压
        bvPoints.add(new Point(bvIds[7],"浮点", "CDAB", 0));
        //状态字
        bvPoints.add(new Point(bvIds[8],"16位整型", "AB", 0));
        //模式
        bvPoints.add(new Point(bvIds[9],"16位整型", "AB", 0));
        //策略
        bvPoints.add(new Point(bvIds[10],"16位整型", "AB", 0));
    }

    public HiwitsDriver(String serial, Integer timeout) {
        super(serial, timeout);
    }

    @Override
    public void readNodeEqu(List<Node> nodeList, TaskFunction function, EquData.EquDataType type) {
        if (!online()) {
            function.doApply(CommStatus.OffLine, nodeList);
            return;
        }
        switch (type) {
            case METER:
                readHeatMeter(nodeList, function);
                break;
            case VALVE:
                readHouseValve(nodeList, function);
                break;
            case PUBLIC_UNIT:
                readBuildValve(nodeList, function);
            default:
        }
    }

    private void readHeatMeter(List<Node> meters, TaskFunction function) {
        for (Node node : meters) {
            HiwitsRequestData requestData = new HiwitsRequestData(serial());
            if ("URT-R2".equalsIgnoreCase(node.getModel())){
                requestData.readHeatMeterOfModbus(node.getSerial());
            }else {
                requestData.readHeatMeter(node.getSerial());
            }
            requestData.setRemain(Collections.singletonList(node));
            sendRequest(requestData, function);
        }
    }

    private void readHouseValve(List<Node> valves, TaskFunction function) {
        for (Node node : valves) {
            HiwitsRequestData requestData = new HiwitsRequestData(serial());
            if ("HiwitsE505_1".equals(node.getModel())) {
                requestData.readHouseValveV20(node.getSerial());
            }
            if ("HiwitsEX03".equals(node.getModel())) {
                requestData.readHouseValveV21(node.getSerial());
            }
            requestData.setRemain(Collections.singletonList(node));
            sendRequest(requestData, function);
        }
    }

    private void readBuildValve(List<Node> valves, TaskFunction function) {
        for (Node node : valves) {
            HiwitsRequestData requestData = new HiwitsRequestData(serial());
            requestData.readBuildValve(node.getSerial());
            requestData.setRemain(Collections.singletonList(node));
            sendRequest(requestData, function);
        }
    }

    @Override
    public void setNodeEquArchive(List<Archive> archives, TaskFunction function) {

    }

    @Override
    public void clearNodeEquArchive(TaskFunction function) {

    }

    @Override
    public void valveOnOffControl(List<Node> valves, boolean ifLock, Integer opening, TaskFunction function) {
        if (!online()) {
            function.doApply(CommStatus.OffLine, valves);
            return;
        }
        for (Node valve : valves) {
            if (valve != null) {
                HiwitsRequestData requestData = new HiwitsRequestData(serial());
                if ("HiwitsE505_1".equals(valve.getModel())) {
                    requestData.houseValveOpenV20(valve.getSerial(), opening, ifLock);
                }
                if ("HiwitsEX03".equals(valve.getModel())) {
                    requestData.houseValveOpenV21(valve.getSerial(), opening);
                }
                requestData.setRemain(valve);
                sendRequest(requestData, function);
            }
        }
    }

    public void valveTemperatureSetting(List<Node> valves, float temperature, float up, float down, TaskFunction function) {
        if (!online()) {
            function.doApply(CommStatus.OffLine, valves);
            return;
        }
        for (Node valve : valves) {
            if (valve != null) {
                HiwitsRequestData requestData = new HiwitsRequestData(serial());
                requestData.houseValveTemp(valve.getSerial(), temperature, up, down);
                requestData.setRemain(valve);
                sendRequest(requestData, function);
            }
        }
    }

    @Override
    public void readNodeRecord(List<Integer> indexes, TaskFunction function) {

    }

    @Override
    public void sentPublicUnitRecord(List<Node> valves, Integer model, Map param, TaskFunction function) {
        if (!online()) {
            function.doApply(CommStatus.OffLine, valves);
            return;
        }
        for (Node valve : valves) {
            if (valve != null) {
                switch (model) {
                    case 1:
                        String co = (String) param.get("controlObject");
                        Float value = Float.parseFloat(param.get("targetValue").toString());
                        HiwitsRequestData requestData = new HiwitsRequestData(serial());
                        if ("阀门开度".equals(co)) {
                            requestData.buildValveOpenTemp(valve.getSerial(), value.intValue(), null);
                        }
                        if ("热表回温".equals(co)) {
                            requestData.buildValveOpenTemp(valve.getSerial(), null, value);
                        }
                        requestData.setRemain(value);
                        sendRequest(requestData, function);
                        break;
                    case 2:
                    case 3:
                    case 4:
                        break;
                    default:
                }
            }
        }
    }

    @Override
    public void sentPublicUnitModel(List<Node> valveSerial, boolean model, TaskFunction function) {

    }

    @Override
    public void sentExtendParam(ExtendParam param, TaskFunction function) {

    }

    @Override
    public void readPublicUnitRecord(Node valveSerial, Integer model, TaskFunction function) {

    }

    @Override
    public void readPublicUnitAndMeter(Node valveSerial, Node meterSerial, TaskFunction function) {

    }

    @Override
    public void heartbeatUpdate() {

    }

    @Override
    public boolean heartStop() {
        return false;
    }

//    public Meter findMeter(String serial) {
//        for (Node meter : bMeters) {
//            if (serial.equals(meter.getSerial())) {
//                return (Meter) meter;
//            }
//        }
//        for (Node meter : hMeters) {
//            if (serial.equals(meter.getSerial())) {
//                return (Meter) meter;
//            }
//        }
//        return null;
//    }
//
//    public Valve findValve(String serial) {
//        for (Node valve : valves) {
//            if (serial.equals(valve.getSerial())) {
//                return (Valve) valve;
//            }
//        }
//        return null;
//    }
//
//    @Override
//    public TempPanel findPanel(String serial) {
//        return null;
//    }
//
//    public PublicUnit findUnit(String serial) {
//        for (Node unit : publicUnit) {
//            if (serial.equals(unit.getSerial())) {
//                return (PublicUnit) unit;
//            }
//        }
//        return null;
//    }
}
